﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace ReporterEngine.Methods
{
    public class AllChilds : BaseMethod
    {
        public override bool IsUseable(LexPath.PathToken token)
        {
            return token.Kind == LexPath.TokenKind.Method && !string.IsNullOrEmpty(token.PathExp) && token.PathExp.ToLower() == "allchilds";
        }

        public override sQuery Execute(LexPath.PathToken token, sQuery query)
        {
            var result = query.New();

            foreach (var element in query.Elements)
            {
                var id = query._model.GetID(element);
                var parentLinks = new List<XElement>();
                if (query._model.REFs.ContainsKey(id.ToString()))
                    parentLinks = query._model.REFs[id.ToString()].Where(x => x.Name.LocalName == "parent").Select(x => x.Parent).ToList();

                var tempLinks = new List<XElement>();

                while (parentLinks.Count > 0)
                {
                    foreach (var parentLink in parentLinks)
                    {
                        if (!result.Elements.Contains(parentLink))
                        {
                            result.Elements.Add(parentLink);
                            var parentID = query._model.GetID(parentLink);

                            //continue
                            //get all child links
                            var tempStartLinks = new List<XElement>();
                            if (query._model.REFs.ContainsKey(parentID.ToString()))
                                tempStartLinks = query._model.REFs[parentID.ToString()].Where(x => x.Name.LocalName == "parent").Select(x => x.Parent).ToList();


                            tempLinks.AddRange(tempStartLinks);
                        }

                        //add all cores if contains
                        var coreElement = query._model.GetXReference(parentLink, "core");
                        if(coreElement != null && !result.Elements.Contains(coreElement))
                        {
                            result.Elements.Add(parentLink);
                            tempLinks.Add(coreElement);
                        }
                    }

                    parentLinks = tempLinks;
                    tempLinks = new List<XElement>();
                }
            }

            return result;
        }

        public override MethodDescription[] GetMethodNames()
        {
            return new MethodDescription[]{new MethodDescription{Name = "allChilds"} };
        }

        //var id = query._model.GetID(element);
        //var startLinks = new List<XElement>();
        //if (query._model.REFs.ContainsKey(id.ToString()))
        //    startLinks = query._model.REFs[id.ToString()].Where(x => x.Name.LocalName == "start").Select(x=>x.Parent).ToList();

        //var tempLinks = new List<XElement>();

        //while(startLinks.Count > 0)
        //{
        //    foreach(var starLink in startLinks)
        //    {
        //        var endEl = starLink.Element("end");
        //        var refID = endEl.Attribute("refid").Value;

        //        var refInst = query._model.IDs[refID];

        //        if(!result.Elements.Contains(refInst))
        //        {
        //            result.Elements.Add(refInst);

        //            //continue
        //            //get all child links
        //            var tempStartLinks = new List<XElement>();
        //            if (query._model.REFs.ContainsKey(refID))
        //                tempStartLinks = query._model.REFs[refID].Where(x => x.Name.LocalName == "start").Select(x => x.Parent).ToList();

        //            tempLinks.AddRange(tempStartLinks);
        //        }
        //    }

        //    startLinks = tempLinks;
        //    tempLinks = new List<XElement>();
        //}
        // all links
        //all objects
    }
}
